/*********************************************************************
*                SEGGER Microcontroller GmbH & Co. KG                *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2014  SEGGER Microcontroller GmbH & Co. KG       *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V5.26 - Graphical user interface for embedded applications **
emWin is protected by international copyright laws.   Knowledge of the
source code may not be used to write a similar product.  This file may
only be used in accordance with a license and should not be re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : Reversi.c
Purpose     : Simple 'reversi' game

              With game engine 'SmartGecko' from
              Energy Micro AS (http://www.energymicro.com)
Requirements: WindowManager - (x)
              MemoryDevices - (x)
              AntiAliasing  - (x)
              VNC-Server    - ( )
              PNG-Library   - ( )
              TrueTypeFonts - ( )
----------------------------------------------------------------------
*/

#include <string.h>
#include <stdio.h>

#include "GUI.h"
#include "DIALOG.h"

/*********************************************************************
*
*       Defines
*
**********************************************************************
*/
#define USE_SMART_GECKO   0

#define NUM_CELL_X        8
#define NUM_CELL_Y        8
#define AA_USE_HIRES      0
#define AA_FACTOR         1u
#define DESKTOP_COLOR     GUI_DARKGREEN
#define CLIENT_COLOR      GUI_DARKGRAY
#define GRID_COLOR        GUI_BROWN
//
// Menu Ids
//
#define ID_MENU_NEW       (GUI_ID_USER +  0)
#define ID_MENU_PASS      (GUI_ID_USER +  1)
#define ID_MENU_EXIT      (GUI_ID_USER +  2)
#define ID_MENU_SETTINGS  (GUI_ID_USER +  3)
#define ID_MENU_ABOUT     (GUI_ID_USER +  4)
#define ID_MENU_TEST      (GUI_ID_USER +  5)

//
// Defines, Player AI 'SmartGecko'
//
#if (USE_SMART_GECKO)
  #define AI_FUNC                     _PlayerAI_SmartGecko
  #define DEPTH                       4
  #define END_GAME_DEPTH              9
  #define INFINITY                    1000000
  #define WINNING_BONUS               100000
  #define VALUE_OF_A_MOVE_POSSIBILITY 15
  #define VALUE_OF_AN_UNSAFE_PIECE    8
  #define VALUE_OF_A_SAFE_PIECE       20
  #define VALUE_OF_A_CORNER           1000
#else
  #define AI_FUNC                     _PlayerAI_FirstValid
#endif

//
// Anti-Aliasing
//
#if AA_USE_HIRES
  #define AA_CALCFACTOR   AA_FACTOR
#else
  #define AA_CALCFACTOR   1u
#endif

/*********************************************************************
*
*       Types
*
**********************************************************************
*/
typedef struct {
  U8  aCells[NUM_CELL_X][NUM_CELL_Y];
  U8  aMoves[NUM_CELL_X][NUM_CELL_Y];
  int ActPlayer;
} BOARD;

typedef char REVERSI_AI_Func(const BOARD * pBoard, int * px, int * py);

/*********************************************************************
*
*       Static data
*
**********************************************************************
*/
static REVERSI_AI_Func * _pPlayerAI[2];
static WM_HWIN           _hFrame;
static BOARD             _Board;
static int               _ShowPossibleMoves = 1;
static int               _CellSize;
static int               _GameOver;
static int               _BoardX0;
static int               _BoardY0;

#if (USE_SMART_GECKO)
  static BOARD           _aBoardStack[END_GAME_DEPTH + 1];
  static int             _aaSafe[10][10];
  static int           * _px;
  static int           * _py;

  static const int _xs[60] = { 
    7, 7, 0, 0, 7, 7, 5, 5, 2, 2, 0, 0, 5, 5, 2, 2, 5, 5, 4, 4, 3, 3, 2, 2,
    7, 7, 4, 4, 3, 3, 0, 0, 6, 6, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 1, 1,
    7, 7, 6, 6, 1, 1, 0, 0, 6, 6, 1, 1
  };

  static const int _ys[60] = { 
    7, 0, 7, 0, 5, 2, 7, 0, 7, 0, 5, 2, 5, 2, 5, 2, 4, 3, 5, 2, 5, 2, 4, 3,
    4, 3, 7, 0, 7, 0, 4, 3, 5, 4, 3, 2, 6, 1, 6, 1, 6, 1, 6, 1, 5, 4, 3, 2,
    6, 1, 7, 0, 7, 0, 6, 1, 6, 1, 6, 1
  };

  static const I32 _aaValues[8][8] = { 
    { 1000, -100, 25,  0,  0, 25, -100, 1000 },
    { -100, -400, -5, -5, -5, -5, -400, -100 },
    {   25,   -5, 12,  2,  2, 12,   -5,   25 },
    {    0,   -5,  2,  2,  2,  2,   -5,    0 },
    {    0,   -5,  2,  2,  2,  2,   -5,    0 },
    {   25,   -5, 12,  2,  2, 12,   -5,   25 },
    { -100, -400, -5, -5, -5, -5, -400, -100 },
    { 1000, -100, 25,  0,  0, 25, -100, 1000 }
  };
#endif

/*********************************************************************
*
*       Static data, SEGGER logo
*
**********************************************************************
*/
static GUI_CONST_STORAGE GUI_COLOR _ColorsSeggerLogo[] = {
  0xFFFFFF, 0xEEEEEE, 0x777777, 0x555555, 0x444444, 0x000000, 0x333333,
  0xDDDDDD, 0xCCCCCC, 0x666666, 0xFF9966, 0xFF3333, 0xFFCCCC, 0xFF6633,
  0xFF3300, 0xFF9999, 0xFFCC99, 0xFF6666, 0xFF0000, 0x888888, 0x222222,
  0x111111, 0x999999, 0xAAAAAA, 0xBBBBBB
};

static GUI_CONST_STORAGE GUI_LOGPALETTE _PalSeggerLogo = {
  25,	// Number of entries
  0, 	// No transparency
  &_ColorsSeggerLogo[0]
};

static GUI_CONST_STORAGE unsigned char _acSeggerLogo[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x02, 0x05, 0x03, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x09, 0x05, 0x09, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0A, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0B, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x10, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x0E, 0x0B, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0C, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0E, 0x11, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x12, 0x0E, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x0E, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0A, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0F, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0B, 0x0E, 0x0B, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x13, 0x14, 0x15, 0x05, 0x14, 0x13, 0x00, 0x00, 0x16, 0x04, 0x06, 0x06, 0x06, 0x06, 0x04, 0x01, 0x00, 0x07, 0x09, 0x15, 0x15, 0x05, 0x06, 0x17, 0x00, 0x00, 0x00, 0x07, 0x09, 0x15, 0x15, 0x05, 0x06, 0x16, 0x00, 0x00, 0x07, 0x04, 0x06, 0x06, 0x06, 0x06, 0x06, 0x17, 0x00, 0x13, 0x04, 0x06, 0x06, 0x06, 0x04, 0x13, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x16, 0x05, 0x04, 0x17, 0x16, 0x14, 0x05, 0x17, 0x00, 0x04, 0x05, 0x04, 0x09, 0x09, 0x09, 0x02, 0x01, 0x01, 0x06, 0x05, 0x09, 0x17, 0x02, 0x05, 0x05, 0x17, 0x00, 0x01, 0x06, 0x05, 0x09, 0x17, 0x02, 0x05, 0x05, 0x16, 0x00, 0x17, 0x05, 0x14, 0x09, 0x09, 0x09, 0x09, 0x18, 0x00, 0x06, 0x05, 0x03, 0x09, 0x03, 0x14, 0x05, 0x13, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x01, 0x00, 0x00, 0x00, 0x09, 0x05, 0x13, 0x00, 0x00, 0x01, 0x16, 0x07, 0x00, 0x03, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0x05, 0x02, 0x00, 0x00, 0x00, 0x17, 0x03, 0x08, 0x00, 0x16, 0x05, 0x09, 0x00, 0x00, 0x00, 0x18, 0x03, 0x18, 0x00, 0x17, 0x05, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x00, 0x00, 0x00, 0x18, 0x05, 0x03, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x18, 0x15, 0x05, 0x15, 0x04, 0x13, 0x07, 0x00, 0x00, 0x03, 0x05, 0x14, 0x06, 0x06, 0x06, 0x13, 0x00, 0x04, 0x05, 0x08, 0x00, 0x00, 0x07, 0x07, 0x07, 0x01, 0x00, 0x03, 0x05, 0x08, 0x00, 0x00, 0x07, 0x07, 0x07, 0x01, 0x00, 0x17, 0x05, 0x15, 0x06, 0x06, 0x06, 0x04, 0x07, 0x00, 0x06, 0x05, 0x16, 0x17, 0x17, 0x03, 0x15, 0x16, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0E, 0x0E, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x13, 0x04, 0x15, 0x05, 0x15, 0x16, 0x00, 0x03, 0x05, 0x04, 0x09, 0x09, 0x09, 0x16, 0x00, 0x04, 0x05, 0x07, 0x00, 0x08, 0x15, 0x15, 0x15, 0x04, 0x00, 0x03, 0x05, 0x08, 0x00, 0x07, 0x15, 0x05, 0x15, 0x06, 0x00, 0x17, 0x05, 0x14, 0x09, 0x09, 0x09, 0x09, 0x01, 0x00, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x01, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x11, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0E, 0x0E, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x17, 0x00, 0x00, 0x01, 0x16, 0x05, 0x14, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x05, 0x16, 0x00, 0x00, 0x18, 0x13, 0x05, 0x14, 0x00, 0x02, 0x05, 0x16, 0x00, 0x00, 0x18, 0x16, 0x05, 0x14, 0x00, 0x17, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x05, 0x08, 0x07, 0x08, 0x04, 0x05, 0x17, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0D, 0x0E, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x05, 0x03, 0x07, 0x01, 0x17, 0x05, 0x04, 0x00, 0x03, 0x05, 0x16, 0x18, 0x18, 0x18, 0x08, 0x01, 0x08, 0x15, 0x15, 0x17, 0x01, 0x07, 0x03, 0x05, 0x14, 0x00, 0x07, 0x15, 0x15, 0x17, 0x01, 0x07, 0x09, 0x05, 0x14, 0x00, 0x17, 0x05, 0x04, 0x18, 0x18, 0x18, 0x18, 0x07, 0x00, 0x06, 0x05, 0x01, 0x00, 0x00, 0x16, 0x05, 0x02, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0B, 0x12, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0E, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x03, 0x05, 0x05, 0x05, 0x05, 0x06, 0x08, 0x00, 0x09, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x17, 0x00, 0x18, 0x14, 0x05, 0x05, 0x05, 0x06, 0x04, 0x14, 0x00, 0x00, 0x18, 0x14, 0x05, 0x05, 0x05, 0x06, 0x04, 0x15, 0x00, 0x08, 0x15, 0x05, 0x05, 0x05, 0x05, 0x05, 0x03, 0x00, 0x06, 0x15, 0x01, 0x00, 0x00, 0x18, 0x05, 0x09, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x0F, 0x11, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x11, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x16, 0x16, 0x17, 0x01, 0x00, 0x00, 0x01, 0x08, 0x18, 0x18, 0x18, 0x18, 0x08, 0x01, 0x00, 0x00, 0x01, 0x17, 0x16, 0x17, 0x00, 0x07, 0x18, 0x00, 0x00, 0x00, 0x01, 0x17, 0x16, 0x17, 0x01, 0x07, 0x17, 0x00, 0x00, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x07, 0x00, 0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x18, 0x07, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x03, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x04, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x16, 0x05, 0x04, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x17, 0x03, 0x05, 0x13, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x03, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04, 0x01, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x02, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x02, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

static GUI_CONST_STORAGE GUI_BITMAP _Logo = {
  90,              // XSize
  46,              // YSize
  90,              // BytesPerLine
   8,              // BitsPerPixel
  _acSeggerLogo,   // Pointer to picture data (indices)
  &_PalSeggerLogo  // Pointer to palette
};

/*********************************************************************
*
*       Function declarations
*
**********************************************************************
*/
static void _StartNewGame(void);

/*********************************************************************
*
*       Static code, helper functions
*
**********************************************************************
*/
/*********************************************************************
*
*       _AddMenuItem
*/
static void _AddMenuItem(MENU_Handle hMenu, MENU_Handle hSubmenu, const char * pText, U16 Id, U16 Flags) {
  MENU_ITEM_DATA Item;

  Item.pText    = pText;
  Item.hSubmenu = hSubmenu;
  Item.Flags    = Flags;
  Item.Id       = Id;
  MENU_AddItem(hMenu, &Item);
}

/*********************************************************************
*
*       _CreateMenu
*/
static void _CreateMenu(WM_HWIN hWin) {
  MENU_Handle hMenuOptions;
  MENU_Handle hMenuGame;
  MENU_Handle hMenuHelp;
  MENU_Handle hMenu;

  MENU_SetDefaultFont(&GUI_Font10_1);
  //
  // Create menu 'Game'
  //
  hMenuGame = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
  _AddMenuItem(hMenuGame, 0, "New game", ID_MENU_NEW,  0);
  _AddMenuItem(hMenuGame, 0, "Pass",     ID_MENU_PASS, 0);
  _AddMenuItem(hMenuGame, 0, NULL,       0,            MENU_IF_SEPARATOR);
  _AddMenuItem(hMenuGame, 0, "Exit",     ID_MENU_EXIT, 0);
  //
  // Create menu 'Options'
  //
  hMenuOptions = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
  _AddMenuItem(hMenuOptions, 0, "Game settings...", ID_MENU_SETTINGS, 0);
  //
  // Create menu 'Help'
  //
  hMenuHelp = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_VERTICAL, 0);
  _AddMenuItem(hMenuHelp, 0, "About Reversi...", ID_MENU_ABOUT, 0);
  //
  // Create main menu
  //
  hMenu = MENU_CreateEx(0, 0, 0, 0, WM_UNATTACHED, 0, MENU_CF_HORIZONTAL, 0);
  _AddMenuItem(hMenu, hMenuGame,    "Game",    0, 0);
  _AddMenuItem(hMenu, hMenuOptions, "Options", 0, 0);
  _AddMenuItem(hMenu, hMenuHelp,    "Help",    0, 0);
  //
  // Attach menu to framewin
  //
  FRAMEWIN_AddMenu(hWin, hMenu);
}

/*********************************************************************
*
*       _CalcBoardDimensions
*/
static void _CalcBoardDimensions(void) {
  GUI_RECT Rect;

  WM_GetClientRectEx(WM_GetClientWindow(_hFrame), &Rect);
  _CellSize = ((Rect.x1 > Rect.y1) ? Rect.y1 : Rect.x1) / 8;
  _BoardX0  = (Rect.x1 - (_CellSize * 8)) / 2;
  _BoardY0  = (Rect.y1 - (_CellSize * 8)) / 2;
}

/*********************************************************************
*
*       _InvalidateBoard
*/
static void _InvalidateBoard(void) {
  WM_InvalidateWindow(WM_GetClientWindow(_hFrame));
}

/*********************************************************************
*
*       _InvalidateCell
*/
static void _InvalidateCell(int x, int y) {
  GUI_RECT Rect;

  Rect.x0 = _BoardX0 + (x * _CellSize);
  Rect.y0 = _BoardY0 + (y * _CellSize);
  Rect.x1 = Rect.x0  + _CellSize - 1;
  Rect.y1 = Rect.y0  + _CellSize - 1;
  WM_InvalidateRect(WM_GetClientWindow(_hFrame), &Rect);
}

/*********************************************************************
*
*       _SetCapture
*/
static void _SetCapture(void) {
  #if (GUI_SUPPORT_MOUSE & GUI_SUPPORT_CURSOR)
    WM_HWIN hWin;

    hWin = WM_GetClientWindow(_hFrame);
    if (WM_HasCaptured(hWin) == 0) {
      WM_SetCapture(hWin, 0);
      GUI_CURSOR_Select(&GUI_CursorCrossS);
    }
  #endif
}

/*********************************************************************
*
*       _ReleaseCapture
*/
static void _ReleaseCapture(void) {
  #if (GUI_SUPPORT_MOUSE & GUI_SUPPORT_CURSOR)
    WM_HWIN hWin;

    hWin = WM_GetClientWindow(_hFrame);
    if (WM_HasCaptured(hWin)) {
      WM_ReleaseCapture();
      GUI_CURSOR_Select(&GUI_CursorArrowM);
    }
  #endif
}

/*********************************************************************
*
*       Static code, game API routines
*
**********************************************************************
*/
/*********************************************************************
*
*       _GetStone
*/
static char _GetStone(const BOARD * pBoard, int x, int y) {
  char r;

  r = 0;
  if ((x >= 0) && (y >= 0) && (x < NUM_CELL_X) && (y < NUM_CELL_Y)) {
    r = pBoard->aCells[x][y];
  }
  return r;
}

/*********************************************************************
*
*       _SetStone
*/
static void _SetStone(BOARD * pBoard, int x, int y) {
  if ((x >= 0) && (y >= 0) && (x < NUM_CELL_X) && (y < NUM_CELL_Y)) {
    pBoard->aCells[x][y] = pBoard->ActPlayer;
    _InvalidateCell(x, y);
  }
}

/*********************************************************************
*
*       _IsValidMove
*/
static char _IsValidMove(BOARD * pBoard, int x, int y) {
  char r;

  r = 0;
  if ((x >= 0) && (y >= 0) && (x < NUM_CELL_X) && (y < NUM_CELL_Y)) {
    r = ((pBoard->aMoves[x][y]) ? 1 : 0);
  }
  return r;
}

/*********************************************************************
*
*       _CheckDirection
*/
static unsigned char _CheckDirection(const BOARD * pBoard, int x, int y, int dx, int dy) {
  char Cell;

  x    += dx;
  y    += dy;
  Cell  = _GetStone(pBoard, x, y);
  if ((Cell != pBoard->ActPlayer) && (Cell != 0)) {
    do {
      x    += dx;
      y    += dy;
      Cell  = _GetStone(pBoard, x, y);
    } while ((Cell != pBoard->ActPlayer) && (Cell != 0));
    return ((Cell == pBoard->ActPlayer) ? 1 : 0);
  }
  return 0;
}

/*********************************************************************
*
*       _CalcValidMoves
*/
static int _CalcValidMoves(BOARD * pBoard) {
  int r;
  int x;
  int y;
  U8  Valid;

  r = 0;
  for (y = 0; y < NUM_CELL_Y; y++) {
    for (x = 0; x < NUM_CELL_X; x++) {
      Valid = 0;
      if (pBoard->aCells[x][y] == 0) {
        Valid |= _CheckDirection(pBoard, x, y, -1, -1) << 0;
        Valid |= _CheckDirection(pBoard, x, y,  0, -1) << 1;
        Valid |= _CheckDirection(pBoard, x, y,  1, -1) << 2;
        Valid |= _CheckDirection(pBoard, x, y,  1,  0) << 3;
        Valid |= _CheckDirection(pBoard, x, y,  1,  1) << 4;
        Valid |= _CheckDirection(pBoard, x, y,  0,  1) << 5;
        Valid |= _CheckDirection(pBoard, x, y, -1,  1) << 6;
        Valid |= _CheckDirection(pBoard, x, y, -1,  0) << 7;
        if (Valid) {
          r++;
        }
      }
      if (Valid != pBoard->aMoves[x][y]) {
        pBoard->aMoves[x][y] = Valid;
        _InvalidateCell(x, y);
      }
    }
  }
  return r;
}

/*********************************************************************
*
*       _DoDirection
*/
static void _DoDirection(BOARD * pBoard, int x, int y, int dx, int dy) {
  do {
    _SetStone(pBoard, x, y);
    x += dx;
    y += dy;
  } while (_GetStone(pBoard, x, y) != pBoard->ActPlayer);
}

/*********************************************************************
*
*       _MakeMove
*/
static void _MakeMove(BOARD * pBoard, int x, int y) {
  U8 Valid;

  _SetStone(pBoard, x, y);
  Valid = pBoard->aMoves[x][y];
  if (Valid & (U8)(1 << 0)) { _DoDirection(pBoard, x, y, -1, -1); }
  if (Valid & (U8)(1 << 1)) { _DoDirection(pBoard, x, y,  0, -1); }
  if (Valid & (U8)(1 << 2)) { _DoDirection(pBoard, x, y,  1, -1); }
  if (Valid & (U8)(1 << 3)) { _DoDirection(pBoard, x, y,  1,  0); }
  if (Valid & (U8)(1 << 4)) { _DoDirection(pBoard, x, y,  1,  1); }
  if (Valid & (U8)(1 << 5)) { _DoDirection(pBoard, x, y,  0,  1); }
  if (Valid & (U8)(1 << 6)) { _DoDirection(pBoard, x, y, -1,  1); }
  if (Valid & (U8)(1 << 7)) { _DoDirection(pBoard, x, y, -1,  0); }
}

/*********************************************************************
*
*       _CalcScore
*/
static int _CalcScore(const BOARD * pBoard) {
  char Cell;
  int  r;
  int  x;
  int  y;

  r = 0;
  for (y = 0; y < NUM_CELL_Y; y++) {
    for (x = 0; x < NUM_CELL_X; x++) {
      Cell = pBoard->aCells[x][y];
      if (Cell) {
        r += (Cell == pBoard->ActPlayer) ? (1) : (-1);
      }
    }
  }
  return r;
}

/*********************************************************************
*
*       Static code, Player AI 'SmartGecko'
*
**********************************************************************
*/
/*********************************************************************
*
*       _ValuePieces
*
* Function description
*   Find the Value of all the pieces belonging to the given Player.
*   A positive Value is good for this Player.
*   The Value can also be negative, if the Player occupies tiles
*   next to a free corner, which makes it easier for the opponent
*   to get to this corner.
*/
#if (USE_SMART_GECKO)
static I32 _ValuePieces(BOARD * pBoard, int Player) {
  I32 Sum;
  int NumberOfSafe;
  int Corners;
  int Changed;
  int xCorner;
  int yCorner;
  int s;
  int x;
  int y;
  
  Sum = 0;
  for (y = 1; y <= 8; y++) {
    for (x = 1; x <= 8; x++) {
      _aaSafe[x][y] = 0;
    }
  }
  Corners  = 0;
  Corners += (pBoard->aCells[0][0] == Player) ? 1 : 0;
  Corners += (pBoard->aCells[7][0] == Player) ? 1 : 0;
  Corners += (pBoard->aCells[0][7] == Player) ? 1 : 0;
  Corners += (pBoard->aCells[7][7] == Player) ? 1 : 0;
  if (Corners) {
    //
    // Corners are the most valuable asset of the position.
    //
    Sum += Corners * VALUE_OF_A_CORNER;
    //
    // Calculate how many pieces are safe, meaning they can never be
    // taken back by the opponent.
    //
    Changed = 0;
    while (Changed == 0) {
      //
      // Repeatedly swipe the board looking for safe pieces,
      // until no more safe pieces are found.
      //
      Changed = 0;
      NumberOfSafe = 0;
      for (y = 1; y <= 8; y++) {
        for (x = 1; x <= 8; x++) {
          if (!_aaSafe[x][y] && pBoard->aCells[x - 1][y - 1] == Player) {
            //
            // A piece can never be taken back if in each of the four directions,
            // one of the two neighboring tiles are safe.
            //
            s =  (_aaSafe[x - 1][y    ] || _aaSafe[x + 1][y    ])  // West  - East
              && (_aaSafe[x    ][y - 1] || _aaSafe[x    ][y + 1])  // North - South
              && (_aaSafe[x - 1][y - 1] || _aaSafe[x + 1][y + 1])  // NW    - SE
              && (_aaSafe[x - 1][y + 1] || _aaSafe[x + 1][y - 1]); // SW    - NE
            if (s) {
              _aaSafe[x][y] = 1;
              Changed = 1;
              ++NumberOfSafe;
            }
          }
        }
        Sum += NumberOfSafe * VALUE_OF_A_SAFE_PIECE;
      }
    }
  }
  //
  // Now add the Value of the unsafe pieces.
  //
  for (y = 0; y < 8; y++) {
    yCorner = (y < 4) ? 0 : 7;
    for (x = 0; x < 8; x++) {
      if (pBoard->aCells[x][y] == Player && !_aaSafe[x + 1][y + 1]) {
        xCorner = x<4 ? 0 : 7;
        if (pBoard->aCells[xCorner][yCorner]) {
          //
          // If the corner is taken, we Value each position in the quadrant the same.
          //
          Sum += VALUE_OF_AN_UNSAFE_PIECE;
        } else {
          //
          // If the corner is still free, we use a lookup table to find the Value of each position.
          //
          Sum += _aaValues[x][y];
        }
      }
    }
  }
  return Sum;
}
#endif

/*********************************************************************
*
*       _Eval
*
* Function description
*   Evaluation function for a Reversi board.
*   Positive Value means Player 1 is in the lead,
*   negative Value means Player 2 is in the lead.
*/
#if (USE_SMART_GECKO)
static I32 _Eval(BOARD * pBoard) {
  int ActPlayer;
  int MovesA;
  int MovesB;
  I32 Score;
  I32 Value;

  ActPlayer = pBoard->ActPlayer;
  pBoard->ActPlayer = 1;
  MovesA    = _CalcValidMoves(pBoard);
  pBoard->ActPlayer = 2;
  MovesB    = _CalcValidMoves(pBoard);
  pBoard->ActPlayer = ActPlayer;
  if (MovesA == 0 && MovesB == 0) {
    //
    // The game is over
    //
    pBoard->ActPlayer = 1;
    Score = _CalcScore(pBoard);
    pBoard->ActPlayer = ActPlayer;
    if (Score==0) {
      return 0;
    }
    if (Score > 0) {
      return Score + WINNING_BONUS;
    }
    if (Score > 0) {
      return Score - WINNING_BONUS;
    }
  }
  //
  // A high number of possible Moves is very valuable
  //
  Value  = VALUE_OF_A_MOVE_POSSIBILITY * (MovesA - MovesB);
  Value += _ValuePieces(pBoard, 1);
  Value -= _ValuePieces(pBoard, 2);
  return Value;
}
#endif

/*********************************************************************
*
*       _Descend
*
* Function description
*   Minimax search for the best possible move with Alpha-Beta pruning
*/
#if (USE_SMART_GECKO)
static I32 _Descend(int Depth, I32 Alpha, I32 Beta, int FirstMove) {
  BOARD * pBoard;
  BOARD * NextBoard;
  int     Maximize;
  int     Moves;
  int     Alt;
  int     i;
  int     x;
  int     y;

  pBoard    = _aBoardStack + Depth;
  NextBoard = _aBoardStack + Depth - 1;
  if (Depth == 0) {
    return _Eval(pBoard);
  }
  Moves = _CalcValidMoves(pBoard);
  if (Moves == 0) {
      //
      // The Player has to pass
      //
      pBoard->ActPlayer = 3 - pBoard->ActPlayer;
      Moves = _CalcValidMoves(pBoard);
      if (Moves == 0) {
        //
        // The game is over
        //
        return _Eval(pBoard);
      }
  }
  Maximize = pBoard->ActPlayer == 1;
  for (i = 0; i < 60; ++i) {
    //
    // Try the possible Moves in order from most attractive to least attractive
    // position, to Maximize the effect of the Alpha-Beta pruning.
    //
    x = _xs[i];
    y = _ys[i];
    if (pBoard->aMoves[x][y]) {
      *NextBoard = *pBoard;
      _MakeMove(NextBoard, x, y);
      NextBoard->ActPlayer = 3 - pBoard->ActPlayer;
      //
      // Recursively evaluate the board resulting from this move.
      //
      Alt = _Descend(Depth - 1, Alpha, Beta, 0);
      if (Maximize) {
        if (Alt > Alpha) {
          Alpha = Alt;
          if (FirstMove) {
            *_px = x;
            *_py = y;
          }
        }
      } else {
        if (Alt < Beta) {
          Beta = Alt;
          if (FirstMove) {
            *_px = x;
            *_py = y;
          }
        }
      }
      if (Beta <= Alpha) {
        break;
      }
    }
  }
  return Maximize ? Alpha : Beta;
}
#endif

/*********************************************************************
*
*       _PlayerAI_SmartGecko
*/
#if (USE_SMART_GECKO)
static char _PlayerAI_SmartGecko(const BOARD * pBoard, int * px, int * py) {
  int FreeTiles;
  int Depth;
  int x;
  int y;

  //
  // Initialize the safe board to true to get the edges right
  //
  for (y = 0; y < 10; y++) {
    for (x = 0; x < 10; x++) {
      _aaSafe[x][y] = 1;
    }
  }
  *px = -1;
  *py = -1;
  _px = px;
  _py = py;
  FreeTiles = 0;
  for (y = 0; y < 8; y++) {
    for (x = 0; x < 8; x++) {
      if (!pBoard->aCells[x][y]) {
        ++FreeTiles;
      }
    }
  }
  Depth = DEPTH;
  if (FreeTiles <= END_GAME_DEPTH) {
    //
    // In the end game, we expand the search Depth.
    //
    Depth = FreeTiles;
  }
  _aBoardStack[Depth] = *pBoard;
  _Descend(Depth, -INFINITY, INFINITY, 1);
  if (*px == -1) {
    return 0;
  }
  return 1;
}
#endif

/*********************************************************************
*
*       Static code, Player AI 'First Valid'
*
**********************************************************************
*/
/*********************************************************************
*
*       _PlayerAI_FirstValid
*/
#if (USE_SMART_GECKO == 0)
static char _PlayerAI_FirstValid(const BOARD * pBoard, int * px, int * py) {
  int x;
  int y;

  for (y = 0; y < NUM_CELL_Y; y++) {
    for (x = 0; x < NUM_CELL_X; x++) {
      if (pBoard->aMoves[x][y]) {
        *px = x;
        *py = y;
        return 1;
      }
    }
  }
  return 0;
}
#endif

/*********************************************************************
*
*       Static code, about box
*
**********************************************************************
*/
/*********************************************************************
*
*       _cbAboutBox
*/
static void _cbAboutBox(WM_MESSAGE * pMsg) {
  WM_HWIN hWin;
  char    acText[16] = "V";

  hWin = pMsg->hWin;
  switch (pMsg->MsgId) {
  case WM_PAINT:
    strcat(acText, GUI_GetVersionString());
    GUI_SetColor(GUI_BLACK);
    GUI_SetFont(&GUI_Font10_1);
    GUI_SetTextMode(GUI_TM_TRANS);
    GUI_DrawBitmap(&_Logo, 4, 4);
    GUI_DispStringHCenterAt("Reversi V1.0", 49, 48);
    GUI_DispStringHCenterAt("emWin", 138, 38);
    GUI_DispStringHCenterAt(acText,  138, 48);
    GUI_DispStringHCenterAt("Compiled " __DATE__ " "__TIME__, 88, 68);
    GUI_DispStringHCenterAt("(c) 1998-2004 Segger", 88, 87);
    GUI_DispStringHCenterAt("Microcontroller Systeme GmbH", 88, 97);
    GUI_DispStringHCenterAt("www.segger.com", 88, 107);
    GUI_DispStringHCenterAt("Programmed by Tobias Quecke", 88, 126);
    break;
  case WM_NOTIFY_PARENT:
    if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
      GUI_EndDialog(hWin, 1);
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _ShowAboutBox
*/
static void _ShowAboutBox(void) {
  WM_HWIN hFrame;
  WM_HWIN hItem;

  //
  // Create framewin
  //
  hFrame = FRAMEWIN_CreateEx(70, 40, 180, 160, WM_HBKWIN, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, "About Reversi", _cbAboutBox);
  FRAMEWIN_SetClientColor   (hFrame, GUI_WHITE);
  FRAMEWIN_SetFont          (hFrame, &GUI_Font10_1);
  FRAMEWIN_SetTextAlign     (hFrame, GUI_TA_HCENTER);
  //
  // Create dialog items
  //
  hItem = BUTTON_CreateEx(111, 7, 55, 18, WM_GetClientWindow(hFrame), WM_CF_SHOW, 0, GUI_ID_OK);
  BUTTON_SetText         (hItem, "Ok");
  //
  // Exec modal dialog
  //
  WM_SetFocus(hFrame);
  WM_MakeModal(hFrame);
  GUI_ExecCreatedDialog(hFrame);
  WM_SetFocus(_hFrame);
}

/*********************************************************************
*
*       Static code, message box
*
**********************************************************************
*/
/*********************************************************************
*
*       _cbMessageBox
*/
static void _cbMessageBox(WM_MESSAGE * pMsg) {
  WM_HWIN hWin;
  int     Id;

  hWin = pMsg->hWin;
  switch (pMsg->MsgId) {
  case WM_NOTIFY_PARENT:
    if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
      Id = WM_GetId(pMsg->hWinSrc);
      GUI_EndDialog(hWin, (Id == GUI_ID_OK) ? 1 : 0);
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _ShowMessageBox
*/
static int _ShowMessageBox(const char * pTitle, const char * pText, int YesNo) {
  WM_HWIN hClient;
  WM_HWIN hFrame;
  WM_HWIN hBut;
  int     r;

  //
  // Create framewin
  //
  hFrame = FRAMEWIN_CreateEx(65, 75, 190, 90, WM_HBKWIN, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, pTitle, _cbMessageBox);
  FRAMEWIN_SetClientColor   (hFrame, GUI_WHITE);
  FRAMEWIN_SetFont          (hFrame, &GUI_Font10_1);
  FRAMEWIN_SetTextAlign     (hFrame, GUI_TA_HCENTER);
  //
  // Create dialog items
  //
  hClient = WM_GetClientWindow(hFrame);
  TEXT_CreateEx(10, 7, 170, 30, hClient, WM_CF_SHOW, GUI_TA_HCENTER, 0, pText);
  if (YesNo) {
    hBut = BUTTON_CreateEx(97, 45, 55, 18, hClient, WM_CF_SHOW, 0, GUI_ID_CANCEL);
    BUTTON_SetText(hBut, "No");
    hBut = BUTTON_CreateEx(32, 45, 55, 18, hClient, WM_CF_SHOW, 0, GUI_ID_OK);
    BUTTON_SetText(hBut, "Yes");
  } else {
    hBut = BUTTON_CreateEx(64, 45, 55, 18, hClient, WM_CF_SHOW, 0, GUI_ID_OK);
    BUTTON_SetText(hBut, "Ok");
  }
  //
  // Exec modal dialog
  //
  WM_SetFocus(hFrame);
  WM_MakeModal(hFrame);
  r = GUI_ExecCreatedDialog(hFrame);
  WM_SetFocus(_hFrame);
  return r;
}

/*********************************************************************
*
*       Static code, dialog settings
*
**********************************************************************
*/
/*********************************************************************
*
*       _cbDialogSettings
*/
static void _cbDialogSettings(WM_MESSAGE * pMsg) {
  WM_HWIN hItem;
  WM_HWIN hWin;

  hWin = pMsg->hWin;
  switch (pMsg->MsgId) {
  case WM_NOTIFY_PARENT:
    if (pMsg->Data.v == WM_NOTIFICATION_RELEASED) {
      hItem = pMsg->hWinSrc;
      switch (WM_GetId(hItem)) {
      case GUI_ID_OK:
        GUI_EndDialog(hWin, 1);
        break;
      case GUI_ID_CHECK0:
        _ShowPossibleMoves = CHECKBOX_GetState(hItem);
        _InvalidateBoard();
        break;
      }
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _ShowDialogSettings
*/
static void _ShowDialogSettings(void) {
  WM_HWIN hClient;
  WM_HWIN hFrame;
  WM_HWIN hItem;

  //
  // Create framewin
  //
  hFrame = FRAMEWIN_CreateEx(70, 75, 180, 90, WM_HBKWIN, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, "Game settings", _cbDialogSettings);
  FRAMEWIN_SetClientColor   (hFrame, GUI_WHITE);
  FRAMEWIN_SetFont          (hFrame, &GUI_Font10_1);
  FRAMEWIN_SetTextAlign     (hFrame, GUI_TA_HCENTER);
  //
  // Create dialog items
  //
  hClient = WM_GetClientWindow(hFrame);
  //
  // Create button
  //
  hItem = BUTTON_CreateEx(59, 46, 55, 18, hClient, WM_CF_SHOW, 0, GUI_ID_OK);
  BUTTON_SetText(hItem, "Ok");
  //
  // Create checkbox
  //
  hItem = CHECKBOX_CreateEx(10, 10, 140, 0, hClient, WM_CF_SHOW, 0, GUI_ID_CHECK0);
  CHECKBOX_SetText   (hItem, "Show possible moves");
  CHECKBOX_SetBkColor(hItem, GUI_INVALID_COLOR);
  CHECKBOX_SetState  (hItem, _ShowPossibleMoves);
  //
  // Exec modal dialog
  //
  WM_SetFocus          (hFrame);
  WM_MakeModal         (hFrame);
  GUI_ExecCreatedDialog(hFrame);
  WM_SetFocus          (_hFrame);
}

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _SetPlayer
*/
static void _SetPlayer(int Player) {
  char ac[256];
  int  PossibleMoves;
  int  ValidMoves;
  int  Score;

  _Board.ActPlayer = Player;
  if (Player == 1) {
    FRAMEWIN_SetText(_hFrame, "Reversi - Player 1");
  } else {
    FRAMEWIN_SetText(_hFrame, "Reversi - Player 2");
  }
  FRAMEWIN_SetBarColor(_hFrame, 1, (Player == 1) ? GUI_RED : GUI_BLUE);
  PossibleMoves = _CalcValidMoves(&_Board);
  GUI_Exec();
  if (!PossibleMoves) {
    GUI_Exec();
    _Board.ActPlayer = 3 - Player;
    ValidMoves       = _CalcValidMoves(&_Board);
    _Board.ActPlayer = Player;
    _CalcValidMoves(&_Board);
    if (ValidMoves) {
      if (_pPlayerAI[_Board.ActPlayer - 1] == NULL) {
        //
        // No valid moves, player must pass
        //
        _ShowMessageBox("Reversi", "No possible moves.\nYou have to pass!", 0);
      }
      _SetPlayer(3 - _Board.ActPlayer);
    } else {
      //
      // No valid moves for all players, game is over
      //
      _GameOver = 1;
      _Board.ActPlayer = 1;
      Score            = _CalcScore(&_Board);
      if (Score > 0) {
        sprintf(ac, "Red wins by %d stones!\nDo you want to start a new game?", Score);
      } else if (Score) {
        sprintf(ac, "Blue wins by %d stones!\nDo you want to start a new game?", -Score);
      } else {
        strcpy (ac, "The game ends in a draw!\nDo you want to start a new game?");
      }
      if (_ShowMessageBox("Reversi", ac, 1)) {
        _StartNewGame();
      }
    }
  }
}

/*********************************************************************
*
*       _NextPlayer
*/
static void _NextPlayer(void) {
  char DoMove;
  int  x;
  int  y;

  do {
    _SetPlayer(3 - _Board.ActPlayer);
    if (_pPlayerAI[_Board.ActPlayer - 1]&& !_GameOver) {
      DoMove = (*_pPlayerAI[_Board.ActPlayer - 1])(&_Board, &x, &y);
      if (DoMove) {
        _MakeMove(&_Board, x, y);
      }
    }
  } while (_pPlayerAI[_Board.ActPlayer - 1] && !_GameOver);
}

/*********************************************************************
*
*       _StartNewGame
*/
static void _StartNewGame(void) {
  memset(&_Board, 0, sizeof(BOARD));
  _Board.aCells[3][3] = 1;
  _Board.aCells[4][4] = 1;
  _Board.aCells[3][4] = 2;
  _Board.aCells[4][3] = 2;
  _GameOver    = 0;
  _SetPlayer(1);
  _InvalidateBoard();
}

/*********************************************************************
*
*       _HandlePID
*/
static void _HandlePID(int x, int y, int Pressed) {
  static int IsInHandlePID = 0;
  unsigned   ReleaseCapture;

  ReleaseCapture = 1;
  if (IsInHandlePID++ == 0) {
    _CalcBoardDimensions();
    x -= _BoardX0;
    y -= _BoardY0;
    if ((x >= 0) && (y >= 0)) {
      x /= _CellSize;
      y /= _CellSize;
      if ((x < 8) && (y < 8)) {
        if (_IsValidMove(&_Board, x, y)) {
          if (Pressed == 0) {
            _ReleaseCapture();
            _MakeMove(&_Board, x, y);
            _NextPlayer();
          } else {
            _SetCapture();
          }
          ReleaseCapture = 0;
        }   
      }
    }
    if (ReleaseCapture) {
      _ReleaseCapture();
    }
  }
  IsInHandlePID--;
}

/*********************************************************************
*
*       _OnTouch
*/
static void _OnTouch(WM_MESSAGE * pMsg) {
  const GUI_PID_STATE * pState;

  pState = (const GUI_PID_STATE *)pMsg->Data.p;
  if (pState) {
    //
    // Something happened in our area (pressed or released)
    //
    _HandlePID(pState->x, pState->y, pState->Pressed);
  }
}

/*********************************************************************
*
*       _OnMouseOver
*/
#if (GUI_SUPPORT_MOUSE & GUI_SUPPORT_CURSOR)
  static void _OnMouseOver(WM_MESSAGE * pMsg) {
    const GUI_PID_STATE * pState;

    pState = (const GUI_PID_STATE *)pMsg->Data.p;
    if (pState) {
      _HandlePID(pState->x, pState->y, -1);
    }
  }
#endif

/*********************************************************************
*
*       _OnMenu
*/
static void _OnMenu(WM_MESSAGE * pMsg) {
  MENU_MSG_DATA * pData;
  MENU_Handle     hMenu;

  pData = (MENU_MSG_DATA *)pMsg->Data.p;
  hMenu = pMsg->hWinSrc;
  switch (pData->MsgType) {
  case MENU_ON_INITMENU:
    if (_GameOver) {
      MENU_DisableItem(hMenu, ID_MENU_PASS);
    } else {
      MENU_EnableItem(hMenu, ID_MENU_PASS);
    }
    break;
  case MENU_ON_ITEMSELECT:
    switch (pData->ItemId) {
    case ID_MENU_NEW:
      _StartNewGame();
      break;
    case ID_MENU_PASS:
      _NextPlayer();
      break;
    case ID_MENU_EXIT:
      WM_DeleteWindow(_hFrame);
      break;
    case ID_MENU_SETTINGS:
      _ShowDialogSettings();
      break;
    case ID_MENU_ABOUT:
      _ShowAboutBox();
      break;
    case ID_MENU_TEST:
      WM_ReleaseCapture();
      break;
    }
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _OnPaint
*/
static void _OnPaint(WM_HWIN hWin) {
  GUI_COLOR Color;
  GUI_RECT  Rect;
  unsigned  rStone;
  unsigned  rMove;
  char      IsValidMove;
  char      Cell;
  int       CellSize;
  int       xCircle;
  int       yCircle;
  int       xPos;
  int       yPos;
  int       x;
  int       y;

  _CalcBoardDimensions();
  GUI_AA_SetFactor(AA_FACTOR);
  #if AA_USE_HIRES
    GUI_AA_EnableHiRes();
  #endif
  LCD_SetBkColor(CLIENT_COLOR);
  WM_GetClientRectEx(hWin, &Rect);
  GUI_ClearRect(Rect.x0,                        Rect.y0,                        Rect.x1,      _BoardY0 - 1);
  GUI_ClearRect(Rect.x0,                        _BoardY0,                       _BoardX0 - 1, _BoardY0 + (8 * _CellSize));
  GUI_ClearRect(_BoardX0 + (8 * _CellSize) + 1, _BoardY0,                       Rect.x1,      _BoardY0 + (8 * _CellSize));
  GUI_ClearRect(Rect.x0,                        _BoardY0 + (8 * _CellSize) + 1, Rect.x1,      Rect.y1);
  CellSize = _CellSize - 1;
  rStone   = ((CellSize - 3) * AA_CALCFACTOR) >> 1;
  rMove    = ((CellSize - 2) * AA_CALCFACTOR) >> 3;
  if (rStone < AA_CALCFACTOR) {
    rStone = AA_CALCFACTOR;
  }
  if (rMove < (AA_CALCFACTOR >> AA_USE_HIRES)) {
    rMove = (AA_CALCFACTOR >> AA_USE_HIRES);
  }
  yPos = _BoardY0;
  for (y = 0; y < 8; y++) {
    xPos = _BoardX0;
    for (x = 0; x < 8; x++) {
      Color = ((x + (y & 1)) & 1) ? GUI_LIGHTGRAY : GUI_WHITE;
      LCD_SetColor(Color);
      GUI_FillRect(xPos + 1, yPos + 1, xPos + CellSize, yPos + CellSize);
      Cell        = _GetStone(&_Board, x, y);
      IsValidMove = (_ShowPossibleMoves) ? _IsValidMove(&_Board, x, y) : 0;
      if (_pPlayerAI[_Board.ActPlayer - 1]) {
        IsValidMove = 0;
      }
      if (Cell || IsValidMove) {
        xCircle = (xPos + 1) * AA_CALCFACTOR + ((CellSize * AA_CALCFACTOR) >> 1);
        yCircle = (yPos + 1) * AA_CALCFACTOR + ((CellSize * AA_CALCFACTOR) >> 1);
        if (Cell) {
          Color = (Cell == 1) ? (GUI_RED) : (GUI_BLUE);
          LCD_SetColor(Color);
          #if (AA_FACTOR > 1)
            GUI_AA_FillCircle(xCircle, yCircle, rStone);
          #else
            GUI_FillCircle(xCircle, yCircle, rStone);
          #endif
        } else {
          LCD_SetColor(GUI_BLACK);
          #if (AA_FACTOR > 1)
            GUI_AA_FillCircle(xCircle, yCircle, rMove);
          #else
            GUI_FillCircle(xCircle, yCircle, rMove);
          #endif
        }
      }
      LCD_SetColor(GRID_COLOR);
      GUI_DrawVLine(xPos, yPos + 1, yPos + CellSize);
      xPos += _CellSize;
    }
    GUI_DrawVLine(xPos, yPos + 1, yPos + CellSize);
    GUI_DrawHLine(yPos, _BoardX0, _BoardX0 + _CellSize * 8);
    yPos += _CellSize;
  }
  GUI_DrawHLine(yPos, _BoardX0, _BoardX0 + _CellSize * 8);
}

/*********************************************************************
*
*       _cbReversiWin
*/
static void _cbReversiWin(WM_MESSAGE * pMsg) {
  WM_HWIN hWin;

  hWin = pMsg->hWin;
  switch (pMsg->MsgId) {
  case WM_PAINT:
    _OnPaint(hWin);
    break;
  case WM_TOUCH:
    _OnTouch(pMsg);
    break;
  #if (GUI_SUPPORT_MOUSE & GUI_SUPPORT_CURSOR)
    case WM_MOUSEOVER:
      _OnMouseOver(pMsg);
      break;
  #endif
  case WM_MENU:
    _OnMenu(pMsg);
    break;
  case WM_DELETE:
    _hFrame = 0;
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       _StartReversi
*/
static void _StartReversi(void) {
  _hFrame = FRAMEWIN_CreateEx(64, 11, 191, 218, WM_HBKWIN, WM_CF_SHOW, FRAMEWIN_CF_MOVEABLE, 0, NULL, _cbReversiWin);
  FRAMEWIN_SetClientColor(_hFrame, GUI_INVALID_COLOR);
  FRAMEWIN_SetFont       (_hFrame, &GUI_Font10_1);
  FRAMEWIN_SetTextAlign  (_hFrame, GUI_TA_HCENTER);
  FRAMEWIN_AddCloseButton(_hFrame, FRAMEWIN_BUTTON_LEFT,  0);
  FRAMEWIN_AddMaxButton  (_hFrame, FRAMEWIN_BUTTON_RIGHT, 0);
  FRAMEWIN_AddMinButton  (_hFrame, FRAMEWIN_BUTTON_RIGHT, 1);
  FRAMEWIN_SetResizeable (_hFrame, 1);
  _CreateMenu(_hFrame);
  _StartNewGame();
  WM_SetFocus(_hFrame);
  while (_hFrame) {
    GUI_Delay(100);
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  GUI_Init();
  GUI_CURSOR_Select(&GUI_CursorArrowM);
  GUI_CURSOR_Show();  
  WM_SetDesktopColor(DESKTOP_COLOR);
  WM_SetCreateFlags(WM_CF_MEMDEV);      // Use memory devices on all windows to avoid flicker
  _pPlayerAI[1] = AI_FUNC;
  while (1) {
    _StartReversi();
    GUI_Delay(1000);
  }
}

/*************************** End of file ****************************/
